package com.example.interceptor;

import com.example.utils.JwtTokenUtil;
import com.example.utils.TokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Component
public class AuthenticationInterception implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 1.如果不是 HandlerMethod（例如静态资源、默认servlet、FilterForward等），直接放行。
        if (!(handler instanceof HandlerMethod))
            return true;

        // 2.放行CORS预检请求（浏览器会先发 OPTIONS）
        // 有时request.getMethod()返回大写，建议用忽略大小写比较
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }

        // 3.如果方法上有JwtIgnore注解，直接通过
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(JwtIgnore.class)) {
            // 拿到注解的值
            boolean value = method.getAnnotation(JwtIgnore.class).value();
            if (value) return true;
        }

        // 4.排除后，开始拦截
        // 从http请求中取出请求头
        String token = request.getHeader(JwtTokenUtil.AUTH_HEADER_KEY);
        // isBlank比isEmpty，还检查是否只包含空白字符
        if(StringUtils.isBlank(token)) {
            throw new RuntimeException("token为空，鉴权失败！");
        }
        // 验证并获取token中的信息
        String tokenInfo = JwtTokenUtil.verifyToken(token);
        // 将token放入本地缓存
        TokenUtil.setToken(tokenInfo);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 方法结束后，移除缓存的token
        TokenUtil.removeToken();
    }
}
